home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / DEMOS / BLUEPONY / BLUEPONY.C next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  10.9 KB  |  508 lines

  1. /* pony.c */
  2.  
  3. /* 
  4.  * By Brian Paul,  written July 31, 1997  for Mark.
  5.  */
  6.  
  7. #include <GL/glut.h>
  8. #include <assert.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include "readtex.h"
  13.  
  14. /* Some <math.h> files do not define M_PI... */
  15. #ifndef M_PI
  16. #define M_PI 3.14159265358979323846
  17. #endif
  18.  
  19. /************************ Pony-specific code *********************************/
  20.  
  21. static float BodyDepth = 0.216;
  22.  
  23. static GLfloat BodyVerts[][2] =
  24. {
  25.   {-0.993334, 0.344444},
  26.   {-0.72, 0.462964},
  27.   {-0.58, -0.411113},
  28.   {-0.406667, -0.692593},
  29.   {0.733334, -0.633334},
  30.   {0.846666, -0.225926},
  31.   {0.873335, -0.55926},
  32.   {0.879998, -0.988888},
  33.   {0.933332, -0.974074},
  34.   {0.953334, -0.537037},
  35.   {0.906667, -0.0777776},
  36.   {0.806666, 0.0333334},
  37.   {-0.26, 0.0111111},
  38.   {-0.406667, 0.27037},
  39.   {-0.54, 0.781481},
  40.   {-0.673333, 1.00371},
  41.   {-0.653332, 0.803704},
  42.   {-1.05333, 0.44815}
  43. };
  44.  
  45. static float LegDepth = 0.144;
  46.  
  47. static float FrontLegPos[3] =
  48. {-0.36, -0.324, 0.108};
  49. static GLfloat FrontLegVerts[][2] =
  50. {
  51.   {-0.23, -0.113481},
  52.   {-0.123333, -0.528296},
  53.   {-0.0926752, -0.728103},
  54.   {-0.0766667, -1.232},
  55.   {0.0233333, -1.232},
  56.   {0.0433332, -0.743111},
  57.   {0.0366667, -0.424593},
  58.   {0.0699998, -0.157926},
  59.   {0.116667, 0.049482},
  60.   {-0.0166667, 0.197629},
  61.   {-0.196667, 0.13837}
  62. };
  63.  
  64. static float BackLegPos[3] =
  65. {0.684, -0.324, 0.108};
  66. static GLfloat BackLegVerts[][2] =
  67. {
  68.   {-0.24, -0.195556},
  69.   {-0.0933332, -0.41037},
  70.   {-0.04, -0.684445},
  71.   {-0.113333, -1.26222},
  72.   {0, -1.26222},
  73.   {0.1, -0.677037},
  74.   {0.213333, -0.121482},
  75.   {0.153333, 0.108148},
  76.   {-0.0533333, 0.211853},
  77.   {-0.26, 0.063702}
  78. };
  79.  
  80. static float ManeDepth = 0.288;
  81. static GLfloat ManeVerts[][2] =
  82. {
  83.   {-0.512667, 0.578519},
  84.   {-0.419333, 0.267407},
  85.   {-0.299333, -0.00666719},
  86.   {-0.239333, -0.0140724},
  87.   {-0.226, 0.0896296},
  88.   {-0.319333, 0.422963},
  89.   {-0.532667, 0.741481}
  90. };
  91.  
  92. static float EyePos[3] =
  93. {-0.702, 0.648, 0.1116};
  94. static float EyeSize = 0.025;
  95.  
  96. /* Display lists */
  97. static GLuint Body = 0, FrontLeg = 0, BackLeg = 0, Mane = 0;
  98.  
  99. /* Generate an extruded, capped part from a 2-D polyline. */
  100. static void 
  101. ExtrudePart(int n, GLfloat v[][2], float depth)
  102. {
  103.   static GLUtriangulatorObj *tobj = NULL;
  104.   int i;
  105.   float z0 = 0.5 * depth;
  106.   float z1 = -0.5 * depth;
  107.   GLdouble vertex[3];
  108.  
  109.   if (tobj == NULL) {
  110.     tobj = gluNewTess();  /* create and initialize a GLU polygon * *
  111.                              tesselation object */
  112.     gluTessCallback(tobj, GLU_BEGIN, glBegin);
  113.     gluTessCallback(tobj, GLU_VERTEX, glVertex2fv);  /* semi-tricky */
  114.     gluTessCallback(tobj, GLU_END, glEnd);
  115.   }
  116.   /* +Z face */
  117.   glPushMatrix();
  118.   glTranslatef(0.0, 0.0, z0);
  119.   glNormal3f(0.0, 0.0, 1.0);
  120.   gluBeginPolygon(tobj);
  121.   for (i = 0; i < n; i++) {
  122.     vertex[0] = v[i][0];
  123.     vertex[1] = v[i][1];
  124.     vertex[2] = 0.0;
  125.     gluTessVertex(tobj, vertex, v[i]);
  126.   }
  127.   gluEndPolygon(tobj);
  128.   glPopMatrix();
  129.  
  130.   /* -Z face */
  131.   glFrontFace(GL_CW);
  132.   glPushMatrix();
  133.   glTranslatef(0.0, 0.0, z1);
  134.   glNormal3f(0.0, 0.0, -1.0);
  135.   gluBeginPolygon(tobj);
  136.   for (i = 0; i < n; i++) {
  137.     vertex[0] = v[i][0];
  138.     vertex[1] = v[i][1];
  139.     vertex[2] = z1;
  140.     gluTessVertex(tobj, vertex, v[i]);
  141.   }
  142.   gluEndPolygon(tobj);
  143.   glPopMatrix();
  144.  
  145.   glFrontFace(GL_CCW);
  146.   /* edge polygons */
  147.   glBegin(GL_TRIANGLE_STRIP);
  148.   for (i = 0; i <= n; i++) {
  149.     float x = v[i % n][0];
  150.     float y = v[i % n][1];
  151.     float dx = v[(i + 1) % n][0] - x;
  152.     float dy = v[(i + 1) % n][1] - y;
  153.     glVertex3f(x, y, z0);
  154.     glVertex3f(x, y, z1);
  155.     glNormal3f(dy, -dx, 0.0);
  156.   }
  157.   glEnd();
  158.  
  159. }
  160.  
  161. /* 
  162.  * Build the four display lists which make up the pony.
  163.  */
  164. static void 
  165. MakePony(void)
  166. {
  167.   static GLfloat blue[4] =
  168.   {0.1, 0.1, 1.0, 1.0};
  169.   static GLfloat black[4] =
  170.   {0.0, 0.0, 0.0, 1.0};
  171.   static GLfloat pink[4] =
  172.   {1.0, 0.5, 0.5, 1.0};
  173.  
  174.   Body = glGenLists(1);
  175.   glNewList(Body, GL_COMPILE);
  176.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
  177.   ExtrudePart(sizeof(BodyVerts) / sizeof(GLfloat) / 2, BodyVerts, BodyDepth);
  178.  
  179.   /* eyes */
  180.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, black);
  181.   glNormal3f(0.0, 0.0, 1.0);
  182.   glBegin(GL_POLYGON);
  183.   glVertex3f(EyePos[0] - EyeSize, EyePos[1] - EyeSize, EyePos[2]);
  184.   glVertex3f(EyePos[0] + EyeSize, EyePos[1] - EyeSize, EyePos[2]);
  185.   glVertex3f(EyePos[0] + EyeSize, EyePos[1] + EyeSize, EyePos[2]);
  186.   glVertex3f(EyePos[0] - EyeSize, EyePos[1] + EyeSize, EyePos[2]);
  187.   glEnd();
  188.   glNormal3f(0.0, 0.0, -1.0);
  189.   glBegin(GL_POLYGON);
  190.   glVertex3f(EyePos[0] - EyeSize, EyePos[1] + EyeSize, -EyePos[2]);
  191.   glVertex3f(EyePos[0] + EyeSize, EyePos[1] + EyeSize, -EyePos[2]);
  192.   glVertex3f(EyePos[0] + EyeSize, EyePos[1] - EyeSize, -EyePos[2]);
  193.   glVertex3f(EyePos[0] - EyeSize, EyePos[1] - EyeSize, -EyePos[2]);
  194.   glEnd();
  195.   glEndList();
  196.  
  197.   Mane = glGenLists(1);
  198.   glNewList(Mane, GL_COMPILE);
  199.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, pink);
  200.   ExtrudePart(sizeof(ManeVerts) / sizeof(GLfloat) / 2, ManeVerts, ManeDepth);
  201.   glEndList();
  202.  
  203.   FrontLeg = glGenLists(1);
  204.   glNewList(FrontLeg, GL_COMPILE);
  205.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
  206.   ExtrudePart(sizeof(FrontLegVerts) / sizeof(GLfloat) / 2,
  207.     FrontLegVerts, LegDepth);
  208.   glEndList();
  209.  
  210.   BackLeg = glGenLists(1);
  211.   glNewList(BackLeg, GL_COMPILE);
  212.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
  213.   ExtrudePart(sizeof(BackLegVerts) / sizeof(GLfloat) / 2,
  214.     BackLegVerts, LegDepth);
  215.   glEndList();
  216. }
  217.  
  218. /* 
  219.  * Draw the pony.  legAngle should be in [-15,15] or so.
  220.  * The pony display lists will be constructed the first time this is called.
  221.  */
  222. static void 
  223. DrawPony(float legAngle)
  224. {
  225.   if (!Body) {
  226.     MakePony();
  227.   }
  228.   assert(Body);
  229.  
  230.   /* BODY */
  231.   glCallList(Body);
  232.  
  233.   /* MANE */
  234.   glCallList(Mane);
  235.  
  236.   /* FRONT +Z LEG */
  237.   glPushMatrix();
  238.   glTranslatef(FrontLegPos[0], FrontLegPos[1], FrontLegPos[2]);
  239.   glRotatef(legAngle, 0.0, 0.0, 1.0);
  240.   glCallList(FrontLeg);
  241.   glPopMatrix();
  242.  
  243.   /* FRONT -Z LEG */
  244.   glPushMatrix();
  245.   glTranslatef(FrontLegPos[0], FrontLegPos[1], -FrontLegPos[2]);
  246.   glRotatef(-legAngle, 0.0, 0.0, 1.0);
  247.   glCallList(FrontLeg);
  248.   glPopMatrix();
  249.  
  250.   /* BACK +Z LEG */
  251.   glPushMatrix();
  252.   glTranslatef(BackLegPos[0], BackLegPos[1], BackLegPos[2]);
  253.   glRotatef(-legAngle, 0.0, 0.0, 1.0);
  254.   glCallList(BackLeg);
  255.   glPopMatrix();
  256.  
  257.   /* BACK -Z LEG */
  258.   glPushMatrix();
  259.   glTranslatef(BackLegPos[0], BackLegPos[1], -BackLegPos[2]);
  260.   glRotatef(legAngle, 0.0, 0.0, 1.0);
  261.   glCallList(BackLeg);
  262.   glPopMatrix();
  263. }
  264.  
  265. /************************* end of pony code **********************************/
  266.  
  267. static float Speed = 2.0;
  268.  
  269. static float LegAngleStep = 0.75;
  270. static float LegMaxAngle = 15.0;
  271. static float LegAngle = 0.0, LegDeltaAngle = 0.5;
  272.  
  273. static float WalkAngle = -90.0, DeltaWalkAngle = 0.225;
  274. static float WalkRadius = 4.0;
  275.  
  276. static float Xrot = 0, Yrot = 30.0;
  277.  
  278. static GLboolean AnimFlag = GL_TRUE;
  279.  
  280. static void 
  281. Idle(void)
  282. {
  283.     /* update animation vars */
  284.     LegAngle += LegDeltaAngle * Speed;
  285.     if (LegAngle > LegMaxAngle) {
  286.       LegDeltaAngle = -LegAngleStep;
  287.     } else if (LegAngle < -LegMaxAngle) {
  288.       LegDeltaAngle = LegAngleStep;
  289.     }
  290.     WalkAngle += DeltaWalkAngle * Speed;
  291.  
  292.     glutPostRedisplay();
  293. }
  294.  
  295. static void 
  296. DrawGround(void)
  297. {
  298.   static GLuint ground = 0;
  299.  
  300.   if (ground == 0) {
  301.     const int rows = 20, columns = 20;
  302.     float sizeA = 1.25, sizeB = 0.2;
  303.     float x, z;
  304.     int i, j;
  305.     GLfloat mat[2][4] =
  306.     {
  307.       {0.0, 0.6, 0.0, 1.0},
  308.       {0.1, 0.8, 0.1, 1.0}
  309.     };
  310.  
  311.     ground = glGenLists(1);
  312.     glNewList(ground, GL_COMPILE);
  313.  
  314.     glNormal3f(0.0, 1.0, 0.0);
  315.  
  316.     x = -(columns * (sizeA + sizeB)) / 4;
  317.     for (i = 0; i <= rows; i++) {
  318.       float size = (i & 1) ? sizeA : sizeB;
  319.       z = -(rows * (sizeA + sizeB)) / 4;
  320.       glBegin(GL_QUAD_STRIP);
  321.       for (j = 0; j <= columns; j++) {
  322.         /* glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat[(i+j)%2]); */
  323.         glColor4fv(mat[(i + j) % 2]);
  324.         glVertex3f(x + size, 0.0, z);
  325.         glVertex3f(x, 0.0, z);
  326.         if (j & 1)
  327.           z += sizeA;
  328.         else
  329.           z += sizeB;
  330.       }
  331.       glEnd();
  332.       x += size;
  333.     }
  334.  
  335.     glEndList();
  336.   }
  337.   glCallList(ground);
  338. }
  339.  
  340. static void 
  341. DrawLogo(void)
  342. {
  343.   glEnable(GL_TEXTURE_2D);
  344.   glShadeModel(GL_SMOOTH);
  345.   glBegin(GL_POLYGON);
  346.   glColor3f(1, 0, 0);
  347.   glTexCoord2f(0, 0);
  348.   glVertex2f(-1.0, -0.5);
  349.   glColor3f(0, 1, 0);
  350.   glTexCoord2f(1, 0);
  351.   glVertex2f(1.0, -0.5);
  352.   glColor3f(0, 0, 1);
  353.   glTexCoord2f(1, 1);
  354.   glVertex2f(1.0, 0.5);
  355.   glColor3f(1, 1, 0);
  356.   glTexCoord2f(0, 1);
  357.   glVertex2f(-1.0, 0.5);
  358.   glEnd();
  359.   glDisable(GL_TEXTURE_2D);
  360.   glShadeModel(GL_FLAT);
  361. }
  362.  
  363. static void 
  364. Display(void)
  365. {
  366.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  367.  
  368.   /* viewing */
  369.   glPushMatrix();
  370.   glRotatef(Xrot, 1.0, 0.0, 0.0);
  371.   glRotatef(Yrot, 0.0, 1.0, 0.0);
  372.  
  373.   /* ground */
  374.   glDisable(GL_LIGHTING);
  375.   glPushMatrix();
  376.   glTranslatef(0.0, -1.6, 0.0);
  377.   DrawGround();
  378.   glPopMatrix();
  379.  
  380.   /* logo */
  381.   glPushMatrix();
  382.   glScalef(2.5, 2.5, 2.5);
  383.   DrawLogo();
  384.   glPopMatrix();
  385.  
  386.   /* pony */
  387.   {
  388.     float xPos, zPos;
  389.     xPos = WalkRadius * cos(WalkAngle * M_PI / 180.0);
  390.     zPos = WalkRadius * sin(WalkAngle * M_PI / 180.0);
  391.     glEnable(GL_LIGHTING);
  392.     glPushMatrix();
  393.     glTranslatef(xPos, 0.0, zPos);
  394.     glRotatef(-WalkAngle + 90.0, 0.0, 1.0, 0.0);
  395.     DrawPony(LegAngle);
  396.     glPopMatrix();
  397.   }
  398.  
  399.   glPopMatrix();
  400.   glutSwapBuffers();
  401. }
  402.  
  403. static void 
  404. Reshape(int width, int height)
  405. {
  406.   float ar;
  407.   glViewport(0, 0, width, height);
  408.   glMatrixMode(GL_PROJECTION);
  409.   glLoadIdentity();
  410.   ar = (float) width / (float) height;
  411.   glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
  412.   glMatrixMode(GL_MODELVIEW);
  413.   glLoadIdentity();
  414.   glTranslatef(0.0, 0.0, -23.0 / 2.5);
  415. }
  416.  
  417. /* ARGSUSED1 */
  418. static void 
  419. Key(unsigned char key, int x, int y)
  420. {
  421.   switch (key) {
  422.   case 27:
  423.     exit(0);
  424.     break;
  425.   case ' ':
  426.     AnimFlag = !AnimFlag;
  427.     if (AnimFlag) {
  428.       glutIdleFunc(Idle);
  429.     } else {
  430.       glutIdleFunc(NULL);
  431.     }
  432.     break;
  433.   }
  434.   glutPostRedisplay();
  435. }
  436.  
  437. /* ARGSUSED1 */
  438. static void 
  439. SpecialKey(int key, int x, int y)
  440. {
  441.   float step = 2.0;
  442.   switch (key) {
  443.   case GLUT_KEY_UP:
  444.     Xrot += step;
  445.     break;
  446.   case GLUT_KEY_DOWN:
  447.     Xrot -= step;
  448.     break;
  449.   case GLUT_KEY_LEFT:
  450.     Yrot -= step;
  451.     break;
  452.   case GLUT_KEY_RIGHT:
  453.     Yrot += step;
  454.     break;
  455.   }
  456.   glutPostRedisplay();
  457. }
  458.  
  459. static void 
  460. Init(void)
  461. {
  462.   GLfloat lightPos[4] =
  463.   {1.0, 10.0, 10.0, 0.0};
  464.   glClearColor(0.5, 0.8, 0.99, 1.0);
  465.   glEnable(GL_DEPTH_TEST);
  466.   glEnable(GL_NORMALIZE);
  467.   glEnable(GL_LIGHTING);
  468.   glEnable(GL_LIGHT0);
  469.   glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
  470.   glShadeModel(GL_FLAT);
  471.  
  472.   LoadRGBMipmaps("logo.bw", 1);
  473. }
  474.  
  475. static void
  476. vis(int visible)
  477. {
  478.   if (visible == GLUT_VISIBLE) {
  479.     if (AnimFlag)
  480.       glutIdleFunc(Idle);
  481.   } else {
  482.     if (AnimFlag)
  483.       glutIdleFunc(NULL);
  484.   }
  485. }
  486.  
  487. int 
  488. main(int argc, char *argv[])
  489. {
  490.   glutInit(&argc, argv);
  491.   glutInitWindowSize(640, 480);
  492.  
  493.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  494.  
  495.   glutCreateWindow("Blue Pony");
  496.  
  497.   Init();
  498.  
  499.   glutReshapeFunc(Reshape);
  500.   glutKeyboardFunc(Key);
  501.   glutSpecialFunc(SpecialKey);
  502.   glutDisplayFunc(Display);
  503.   glutVisibilityFunc(vis);
  504.  
  505.   glutMainLoop();
  506.   return 0;             /* ANSI C requires main to return int. */
  507. }
  508.